use crypto::aes;
use crypto::aes::KeySize::KeySize256;
use crypto::blockmodes::PkcsPadding;
use crypto::buffer::{BufferResult, ReadBuffer, RefReadBuffer, RefWriteBuffer, WriteBuffer};
use crypto::symmetriccipher::SymmetricCipherError;

pub use cmd::{CmdUtil};
pub use config::{AppConfig, DeployConfig, init_config, Profile, read_config};
pub use constants::*;

use crate::{AES_IV_ARR, AES_KEY_ARR};

mod config;
mod constants;
mod cmd;


pub fn aes256_cbc_encrypt(data: &[u8]) -> Result<Vec<u8>, SymmetricCipherError> {
    let aes_key: &Vec<u8> = AES_KEY_ARR.get().unwrap();
    let aes_iv: &Vec<u8> = AES_IV_ARR.get().unwrap();

    let mut encryptor = aes::cbc_encryptor(KeySize256, aes_key, aes_iv, PkcsPadding);
    let mut buffer = [0; 4096];
    let mut write_buffer = RefWriteBuffer::new(&mut buffer);
    let mut read_buffer = RefReadBuffer::new(data);
    let mut final_result = Vec::new();
    loop {
        let result = encryptor.encrypt(&mut read_buffer, &mut write_buffer, true)?;
        final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().copied());
        match result {
            BufferResult::BufferUnderflow => break,
            _ => continue,
        }
    }

    Ok(final_result)
}

pub fn aes256_cbc_decrypt(data: &[u8]) -> Result<Vec<u8>, SymmetricCipherError> {
    let aes_key: &Vec<u8> = AES_KEY_ARR.get().unwrap();
    let aes_iv: &Vec<u8> = AES_IV_ARR.get().unwrap();

    let mut decryptor = aes::cbc_decryptor(KeySize256, aes_key, aes_iv, PkcsPadding);
    let mut buffer = [0; 4096];
    let mut write_buffer = RefWriteBuffer::new(&mut buffer);
    let mut read_buffer = RefReadBuffer::new(data);
    let mut final_result = Vec::new();

    loop {
        let result = decryptor.decrypt(&mut read_buffer, &mut write_buffer, true)?;
        final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().copied());
        match result {
            BufferResult::BufferUnderflow => break,
            _ => continue,
        }
    }
    Ok(final_result)
}